package com.zj.juc.study.reternLock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.StampedLock;

/**
 * @author 自己的名字
 * @version 1.0.0
 * @ClassName StampedLockDemo
 * @Description 邮戳锁
 * @createTime 2025年01月05日 18:14
 */
public class StampedLockDemo {

    static int number = 37;

    static StampedLock lock = new StampedLock();

    public static void main(String[] args) {
        StampedLockDemo demo = new StampedLockDemo();
//        new Thread(()->{
//            demo.read();
//        },"read").start();
//
//        try {
//            TimeUnit.SECONDS.sleep(1);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        new Thread(()->{
//            demo.write();
//        },"write").start();

        new Thread(()->{
            demo.readHappy();
        },"read").start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            demo.write();
        },"write").start();
    }

    public void write(){

        System.out.println("写线程进入.....");
        //加写锁，返回邮戳
        long stamp = lock.writeLock();
        System.out.println(Thread.currentThread().getName() + "\t" + "写线程准备修改");
        try {
            number = number+20;
        }finally {
            //写锁解锁
            lock.unlockWrite(stamp);
        }
        System.out.println(Thread.currentThread().getName()+"\t"+"写线程结束修改");
    }


    /**
     * 悲观读，读没有完成写锁无法获得
     */
    public void read(){
        //加读锁，返回邮戳
        long stamp = lock.readLock();

        System.out.println(Thread.currentThread().getName() + "\t" + "读锁come in");
        for (int i = 0; i < 4; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait.....");
        }

        try {
            int result = number;
            System.out.println(Thread.currentThread().getName()+"\t"+"get result"+result);
            System.out.println("写线程失败,读锁时写锁无法介入，传统的读写互斥");
        } finally {
            lock.unlockRead(stamp);
        }
    }


    /**
     * 乐观读,读的过程中没人改的话就是乐观，有人改变更为悲观读 validate无修改，false有修改
     */
    public void readHappy(){
        long stamp = lock.tryOptimisticRead();
        int result = number;
        //故意间隔四秒，乐观认为读过程中没有线程修改number,具体靠判断
        System.out.println("四秒前:"+"\t"+lock.validate(stamp));
        for (int i = 0; i < 4; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"reading..."+(i+1)+"秒后:"+lock.validate(stamp));
            if (!lock.validate(stamp)){
                System.out.println("有人修改");
                stamp = lock.readLock();//从乐观锁变更为悲观锁
                try {
                    System.out.println("从乐观读升级为悲观读");
                    result = number;
                    System.out.println("重新悲观"+result);
                }finally {
                    lock.unlockRead(stamp);
                }
            }
            System.out.println("返回true，无修改"+result);
        }

    }

}
